package com.example.order.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.example.order.service.SentinelService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * @Author 刘武贵
 * @Date 2024-03-03 21:28
 * @Description 功能描述：测试Sentinel
 */
@Slf4j
@RestController
public class SentinelController {

    /**
     * 测试Sentinel
     */
    @Resource
    private SentinelService sentinelService;

    /**
     * 处理请求以测试Sentinel1的功能。（演示Sentinel的链路流控模式）
     * 该方法不做任何参数接收，并返回一个简单的字符串标识。
     *
     * @return 返回字符串"sentinel1"，表示Sentinel1测试完成。
     */
    @GetMapping(value = "/request_sentinel1")
    public String requestSentinel1(){
        // 记录日志信息，表示开始测试Sentinel1
        log.info("测试Sentinel1");
        // 调用sentinelService发送消息
        sentinelService.sendMessage();
        // 返回标识字符串
        return "sentinel1";
    }

    /**
     * 处理请求以测试Sentinel2的功能。（演示Sentinel的熔断规则、）
     * 与requestSentinel1相似，但针对Sentinel2进行测试。
     *
     * @return 返回字符串"sentinel2"，表示Sentinel2测试完成。
     */
    @GetMapping(value = "/request_sentinel2")
    public String requestSentinel2(){
        // 记录日志信息，开始测试Sentinel2
        log.info("测试Sentinel2");
        // 发送消息，测试Sentinel2的服务功能
        sentinelService.sendMessage();
        // 返回标识字符串
        return "sentinel2";
    }

    /**
     * 处理来自客户端的请求，演示如何使用Sentinel进行资源保护。（演示Sentinel的热点规则、）
     * 访问链接：http://localhost:8080/order/request_sentinel3?header=header 会触发限流
     * 访问链接：http://localhost:8080/order/request_sentinel3?body=body 不会触发限流
     *
     * @param header 请求头信息，用于日志记录，不参与逻辑处理。
     * @param body 请求体信息，用于日志记录，不参与逻辑处理。
     * @return 返回一个固定字符串"sentinel3"，用于客户端识别请求处理结果。
     */
    @GetMapping(value = "/request_sentinel3")
    @SentinelResource("request_sentinel3")
    public String requestSentinel3(String header, String body){
        log.info("测试Sentinel3");
        return "sentinel3";
    }

    /**
     * 计数器变量，用于记录某些操作的次数或状态。
     */
    private int count = 0;

    /**
     * 处理来自客户端的请求，演示如何使用Sentinel进行异常比例熔断。（演示Sentinel的基于异常比例熔断、基于异常数熔断、授权规则）
     * 访问链接：http://localhost:8080/order/request_sentinel4?serverName=test
     *
     * @return 返回一个固定字符串"sentinel4"，用于客户端识别请求处理结果。
     *         该方法会模拟抛出运行时异常，异常抛出的概率为50%。
     */
    @GetMapping(value = "/request_sentinel4")
    @SentinelResource("request_sentinel4")
    public String requestSentinel4(){
        log.info("测试Sentinel4");
        count++;
        // 模拟异常，抛出异常的概率为50%
        if (count % 2 == 0){
            throw new RuntimeException("演示基于异常比例熔断");
        }
        return "sentinel4";
    }

    /**
     * 处理GET请求的控制器方法，用于测试Sentinel的流量控制功能。（演示Sentinel的系统规则）
     *
     * @return 返回一个字符串"sentinel5"。
     */
    @GetMapping(value = "/request_sentinel5")
    @SentinelResource("request_sentinel5")
    public String requestSentinel5(){
        log.info("测试Sentinel5");
        return "sentinel5";
    }

    /**
     * 处理GET请求的控制器方法，用于测试通过服务发送消息的流量控制。（演示@SentinelResource注解、Sentinel持久化）
     *
     * @return 返回通过sentinelService.sendMessage2()方法发送的消息内容。
     */
    @GetMapping(value = "/request_sentinel6")
    public String requestSentinel6(){
        log.info("测试Sentinel6");
        return sentinelService.sendMessage2();
    }
}
